# -*- coding: utf-8 -*-
"""Example of using kNN for outlier detection
"""
# Author: Yue Zhao <zhaoy@cmu.edu>
# License: BSD 2 clause

from __future__ import division
from __future__ import print_function

import os
import sys

# temporary solution for relative imports in case pyod is not installed
# if pyod is installed, no need to use the following line
sys.path.append(
    os.path.abspath(os.path.join(os.path.dirname("__file__"), '..')))

from pyod.models.knn import KNN
from pyod.models.pca import PCA
from pyod.models.rgraph import RGraph
from pyod.models.lof import LOF
from pyod.models.cof import COF
from pyod.models.iforest import IForest
from pyod.models.kde import KDE
from pyod.models.copod import COPOD
from pyod.models.suod import SUOD
from pyod.models.rod import ROD
from pyod.utils.data import generate_data


def outlier_detection(data, clf_name='KNN'):
    if clf_name == 'KNN':
        clf = KNN()
    elif clf_name == 'PCA':
        clf = PCA(n_components=3)
    elif clf_name == 'R-graph':
        clf = RGraph(n_nonzero=100, transition_steps=20, gamma=50, blocksize_test_data=20,
                     tau=1, preprocessing=True, active_support=False, gamma_nz=False,
                     algorithm='lasso_lars', maxiter=100, verbose=1)
    elif clf_name == 'LOF':
        clf = LOF()
    elif clf_name == 'COF':
        clf = COF(n_neighbors=30)
    elif clf_name == 'IForest':
        clf = IForest()
    elif clf_name == 'KDE':
        clf = KDE()
    elif clf_name == 'COPOD':
        clf = COPOD()
    elif clf_name == 'ROD':
        clf = ROD()
    elif clf_name == 'SUOD':
        clf_name = 'SUOD'

        # initialized a group of outlier detectors for acceleration
        detector_list = [LOF(n_neighbors=15), LOF(n_neighbors=20),
                         LOF(n_neighbors=25), LOF(n_neighbors=35),
                         COPOD(), IForest(n_estimators=100),
                         IForest(n_estimators=200)]

        # decide the number of parallel process, and the combination method
        clf = SUOD(base_estimators=detector_list, n_jobs=2, combination='average',
                   verbose=False)

    else:
        print("{} isn't a valid algorithn name!".format(clf_name))
        raise NotImplementedError

    clf.fit(data)
    # get the prediction labels and outlier scores of the training data
    y_train_pred = clf.labels_  # binary labels (0: inliers, 1: outliers)
    y_train_scores = clf.decision_scores_  # raw outlier scores
    return y_train_pred, y_train_scores, clf


# from pyod.utils.example import visualize

if __name__ == "__main__":
    contamination = 0.1  # percentage of outliers
    n_train = 200  # number of training points
    n_test = 400  # number of testing points

    # Generate sample data
    X_train, X_test, y_train, y_test = \
        generate_data(n_train=n_train,
                      n_test=n_test,
                      n_features=6,
                      contamination=contamination,
                      random_state=42)

    # train kNN detector
    clf_name = 'SUOD'
    label, score, model = outlier_detection(X_train, clf_name)

    print(label, y_train)